package com.hardson.toolkit.swing.table;

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.DefaultTableModel;

/**
 *
 * @author fanhoujun
 *
 */
public class TableContent {
	private static final int MAX_COLUMN = 128;//定义表格的最大列数

	private List<CellData> list = new ArrayList<CellData>();

	private int rowCount = 0;

	private boolean isNewLine = true;

	/**
	 * 连续多次调用等同于一次调用。
	 */
	public void println() {
		if (this.isNewLine) {
			return;
		}
		this.list.add(null);
		this.rowCount++;
		this.isNewLine = true;
	}

	public void append(final Object value) {
		this.append(value, 1, 1);
	}

	public void append(final Object value, final int colSpan) {
		this.append(value, colSpan, 1);
	}

	public void append(final Object value, final int colSpan, final int rowSpan) {
		if (colSpan < 1 || rowSpan < 1) {
			throw new IllegalArgumentException(
					"colSpan和rowSpan都必需大于0(colSpan:+" + colSpan + ",rowSpan:" + rowSpan + ")");
		}
		if (this.isNewLine) {
			this.isNewLine = false;
		}
		this.list.add(new CellData(value, colSpan, rowSpan));
	}

	public DTable createTable() {
		return this.createTable(null);
	}

	@SuppressWarnings("unchecked")
	public DTable createTable(Object[] columnHeaders) {
		this.println();
		List<CellData>[] listData = new List[this.rowCount];
		for (int i = 0; i < listData.length; i++) {
			listData[i] = new ArrayList<CellData>();
		}
		CellData[][] cover = new CellData[this.rowCount][100];//记录被跨过（覆盖的）单元格
		int cusorRow = 0;//行游标
		int cusorCol = 0;//列游标
		int column = 0;//记录表格的列数（取所有行的最多列）
		for (CellData cellData : this.list) {
			if (cellData != null) {
				if (cusorCol == MAX_COLUMN) {
					throw new RuntimeException("表格的列数不能超过" + MAX_COLUMN + "列");
				}
				while (cover[cusorRow][cusorCol] != null) {
					cusorCol++;
					listData[cusorRow].add(null);
				}
				listData[cusorRow].add(cellData);
				this.setSpanHidden(cusorRow, cusorCol, cellData, cover);
				while (cover[cusorRow][++cusorCol] != null) {
					listData[cusorRow].add(null);
				}
			} else {
				column = column < cusorCol ? cusorCol : column;
				cusorCol = 0;
				cusorRow++;
			}
		}
		if (columnHeaders == null) {
			columnHeaders = new Object[column];
		}
		DefaultTableModel model = this.createTableModel(listData, columnHeaders, false);
		return new DTable(new GridSplitImpl(listData, cover), model);
	}

	private DefaultTableModel createTableModel(final List<CellData>[] listData,
			final Object[] columnHeaders, final boolean cellEditable) {
		Object[][] data = new Object[listData.length][columnHeaders.length];
		int row = 0;
		for (List<CellData> rowList : listData) {
			int col = 0;
			for (CellData cellData : rowList) {
				data[row][col++] = cellData == null ? null : cellData.getValue();
			}
			row++;
		}
		DefaultTableModel model = new DefaultTableModel(data, columnHeaders) {
			private static final long serialVersionUID = 1L;

			@Override
			public boolean isCellEditable(final int row, final int column) {
				return cellEditable;
			}
		};
		return model;
	}

	/**
	 * 将该单元跨过的其他单元格的状态设为隐藏
	 *
	 * @param row
	 * @param col
	 */
	private void setSpanHidden(final int row, final int col, final CellData cellData,
			final CellData[][] cover) {
		if (cellData.getColSpan() < 2 && cellData.getRowSpan() < 2) {
			return;
		}
		CellData coverData = CellData.creatHiddenCell(row, col);
		if (col + cellData.getColSpan() >= MAX_COLUMN) {
			throw new RuntimeException("表格的列数不能超过" + MAX_COLUMN + "列");
		}

		for (int i = 0; i < cellData.getColSpan(); i++) {
			for (int j = 0; j < cellData.getRowSpan(); j++) {
				if (row + j < cover.length) {
					cover[row + j][col + i] = coverData;
				} else {
					cellData.setRowSpan(j);
				}
			}
		}
		cover[row][col] = null;
	}

}
